import blue
import uix
import uiutil
import listentry
import base
import menu
import log
import types
import uthread
import sys
import uicls
import uiconst

def Window(name, icon = None, closeFunc = None):
    wnd = sm.GetService('window').GetWindow(name, create=1)
    wnd.SetScope('all')
    if (icon is None):
        wnd.SetWndIcon(None)
        wnd.SetTopparentHeight(0)
    if (closeFunc is not None):
        wnd.DoClose = closeFunc
    return wnd


ENTRY_HASSUBMENU = 1L
ENTRY_ISDYNAMIC = 2L
ENTRY_VADJUST = 4L
ADDTOP = 2
MENUWIDTH = 64
BARWIDTH = 24
TRACEWIDTH = 7
HILITEALPHA = 0.25
GHOSTALPHA = 0.5
SPACER = 4

def MenuHeader(label, **kw):
    entry = {'label': label,
     'flags': ENTRY_VADJUST,
     'height': 16,
     'hilited': 2,
     'disabled': True}
    entry.update(kw)
    return entry



class MenuEntry(uicls.Container):
    __module__ = __name__
    __guid__ = 'spiffy.MenuEntry'

    def Setup(self, entry, menuobj = None, fontsize = None, addleft = 3):
        self.hilited = self.ghosted = self.disabled = False
        self.flags = 0L
        self.action = self.args = self.iconmap = None
        self.iconmapscaling = 0.25
        self.fontsize = fontsize
        self.menuobj = menuobj
        if (type(entry) == types.DictType):
            for (k, v,) in entry.iteritems():
                setattr(self, k, v)

        elif (type(entry) == types.TupleType):
            label = entry[0]
            if (type(label) == types.TupleType):
                self.label = label[0]
                if (len(label) > 1):
                    self.iconmap = label[1]
                    if (len(label) > 2):
                        self.iconmapscaling = label[2]
                else:
                    self.iconmap = '09_14'
            else:
                self.label = label
                self.iconmap = None
            action = entry[1]
            if (type(action) == types.TupleType):
                if (action[0] == 'isDynamic'):
                    self.flags |= (ENTRY_HASSUBMENU | ENTRY_ISDYNAMIC)
                    self.action = action[1]
                    if (len(action) > 2):
                        self.args = action[2]
                else:
                    raise TypeError, 'Unsupported submenu type'
            elif (type(action) == types.ListType):
                self.flags |= ENTRY_HASSUBMENU
                self.action = action
            else:
                if (callable(action) and (not self.disabled)):
                    self.action = action
                    if (len(entry) >= 3):
                        self.args = entry[2]
            self.action = None
        else:
            raise TypeError, 'Unsupported entry definition type'
        if self.fontsize:
            self.hspace = 0
        elif (self.height <= 16):
            self.fontsize = 10
            self.hspace = 1
        else:
            self.fontsize = 12
            self.hspace = 1
        self.name = self.label
        if not self.action:
            self.disabled = True
        if (self.disabled and (not self.hilited)):
            self.ghosted = True
        if hasattr(self, 'OnPreCreate'):
            self.OnPreCreate(self)
        self.sr.leftedge = uicls.Container(name='push', parent=self, width=addleft, state=uix.UI_DISABLED, align=uiconst.TOLEFT)
        if self.iconmap:
            self.sr.icon = icon = uicls.Icon(parent=self, align=uiconst.TOLEFT, state=uiconst.UI_DISABLED)
            if (type(self.iconmap) is int):
                icon.ChangeIcon(iconID=self.iconmap, size=self.height, ignoreSize=True)
            else:
                icon.ChangeIcon(icon=self.iconmap, size=self.height, ignoreSize=True)
            icon.left = addleft
            if self.ghosted:
                icon.color.a = GHOSTALPHA
        SPACER = 4
        uicls.Container(name='push', parent=self, width=SPACER, state=uix.UI_DISABLED, align=uiconst.TOLEFT)
        indent = ((self.sr.leftedge.width + (self.height, 0)[(not self.iconmap)]) + SPACER)
        self.sr.label = uicls.Label(text=self.label, parent=self, fontsize=self.fontsize, letterspace=self.hspace, state=uiconst.UI_DISABLED, left=indent)
        self.sr.label.top = (((self.height - self.sr.label.textheight) / 2) + 1)
        if self.ghosted:
            self.sr.label.color.a = GHOSTALPHA
        self.width = ((((indent + self.sr.label.textwidth) + SPACER) + SPACER) + 3)
        if (self.flags & ENTRY_HASSUBMENU):
            self.triangle = triangle = uiutil.GetChild(self, 'TriangleRight')
            triangle.state = uix.UI_DISABLED
            triangle.top = ((self.height - 10) / 2)
            triangle.left += 2
        self.children[1].state = uix.UI_HIDDEN
        self.sr.selection2 = self.children[2]
        if (self.hilited == 2):
            c = (0.0, 0.0, 0.0, 0.2)
        else:
            c = (1.0, 1.0, 1.0, 0.25)
        self.sr.selection = uicls.Fill(parent=self, idx=0, color=c, align=uiconst.TOALL)
        self.sr.selection.state = uiconst.UI_HIDDEN
        if self.iconmap:
            self.sr.iconbg = uicls.Fill(parent=self, idx=-1, color=(0, 0, 0, 0.2), left=addleft, top=0, width=self.height, height=self.height, align=uiconst.TOPLEFT)
        if hasattr(self, 'OnPostCreate'):
            self.OnPostCreate(self)
        if self.hilited:
            self._OnMouseEnter()



    def _OnMouseEnter(self, *args):
        if (self.hilited or (not self.disabled)):
            self.sr.selection.state = uix.UI_DISABLED
            if self.iconmap:
                self.sr.iconbg.state = uix.UI_HIDDEN



    def _OnMouseExit(self, *args):
        if not self.hilited:
            self.sr.selection.state = uix.UI_HIDDEN
            if self.iconmap:
                self.sr.iconbg.state = uix.UI_DISABLED



    def _OnMouseUp(self, *args):
        if self.disabled:
            return 
        if not (self.flags & ENTRY_HASSUBMENU):
            uthread.new(menu.KillAllMenus)
            if self.args:
                uthread.new(self.action, *self.args)
            else:
                uthread.new(self.action)



    def GetSubContent(self):
        if (self.flags & ENTRY_ISDYNAMIC):
            try:
                if self.args:
                    m = self.action(*self.args)
                else:
                    m = self.action()
            except Exception, e:
                log.LogException()
                print str(e)
                m = [{'label': 'ERROR',
                  'disabled': True,
                  'ghosted': True,
                  'action': None,
                  'iconmap': '44_08',
                  'iconmapscaling': 0.125}]
                sys.exc_clear()
        else:
            m = self.action
        return m




class Menu(uicls.Container):
    __guid__ = 'spiffy.Menu'

    def init(self):
        self.submenu = None
        self.hilitedentry = None



    def Setup(self, menu, entryheight = 16, position = None, origin = 'topleft', caption = None, fromentry = None, reverse = False):
        self.reverse = reverse
        self.origin = origin
        self.entryheight = entryheight
        self.fromentry = fromentry
        if fromentry:
            self.parentmenu = self.fromentry.menuobj
        menulayer = uicore.layer.menu
        if not fromentry:
            uix.Flush(menulayer)
        self.state = uix.UI_HIDDEN
        self.align = uix.UI_ALNONE
        menulayer.children.insert(0, self)
        container = uicls.Container(name='SpiffyEntryList', parent=self, idx=0, pos=(0, 0, 0, 0))
        height = 0
        width = 0
        uicls.Container(name='push', parent=container, align=uiconst.TOTOP, height=2)
        allflags = 0
        wasline = 1
        if (caption or fromentry):
            margin = (0, 1)[(not fromentry)]
        else:
            margin = 5
        if not menu:
            menu = [{'label': 'No items',
              'disabled': True,
              'ghosted': True,
              'action': None,
              'iconmap': '44_08',
              'iconmapscaling': 0.125}]
        while (menu[-1] is None):
            menu.pop()

        addtop = 0
        for entry in menu:
            if entry:
                item = MenuEntry(blue.os.LoadObject('res:/UI/Shared/contextualentry.blue'))
                item.align = uix.UI_ALTOP
                item.height = entryheight
                item.Setup(entry, addleft=margin, menuobj=self)
                item.OnMouseEnter = self.OnEntryEnter
                item.OnMouseExit = self.OnEntryExit
                width = max(width, item.width)
                if ((item.flags & ENTRY_VADJUST) and (fromentry and (not height))):
                    addtop = item.height
                allflags |= item.flags
                wasline = 0
            elif wasline:
                continue
            item = blue.os.LoadObject('res:/UI/Component/line_horizontal.blue')
            item.align = uix.UI_ALTOP
            wasline = 1
            container.children.append(item)
            height += item.height

        if (fromentry and (item and (item.flags & ENTRY_VADJUST))):
            subbottom = item.height
        else:
            subbottom = 0
        if (allflags & ENTRY_HASSUBMENU):
            addwidth = 8
        else:
            addwidth = 0
        self.height = ((ADDTOP + height) + ADDTOP)
        if (fromentry and (not caption)):
            addwidth += TRACEWIDTH
            edge = uicls.Container(name='SpiffyBar', parent=container, align=uiconst.TOLEFT, width=TRACEWIDTH, idx=0)
            self.sr.trace = side = uicls.Fill(parent=self, align=uiconst.TOPLEFT, left=0, top=0, width=TRACEWIDTH, idx=0)
        else:
            edge = None
            if caption:
                raise RuntimeError('SpiffyBar is still broken and needs fixing')
                addwidth += BARWIDTH
                side = uix.GetFill(uicls.Container(name='SpiffyBar', parent=container, align=uiconst.TOLEFT, width=BARWIDTH, idx=0))
                t = uicls.Label(text=caption, parent=side, fontsize=uix.UIFONT_9X17, width=self.height, height=BARWIDTH, autowidth=False, autoheight=False, state=uiconst.UI_NORMAL)
                sm.GetService('textmetr').RefreshHeight(t)
                t.left = ((((BARWIDTH - self.height) + t.height) / 2) + 1)
                t.height = BARWIDTH
                t.top = ((((self.height - BARWIDTH) / 2) - 1) - 12)
                t.rotation = 90.0
                t.control.model.areas[0].areaMaterials[0].diffuse.a = 0.66
            else:
                side = None
        if side:
            side.color.SetRGB(1.0, 1.0, 1.0, HILITEALPHA)
        self.width = (max(MENUWIDTH, width) + addwidth)
        if fromentry:
            p = self.parentmenu
            while True:
                if self.reverse:
                    left = ((p.absoluteLeft - self.width) + 3)
                else:
                    left = (p.absoluteRight - 5)
                if ((left < 0) or ((left + self.width) > eve.triapp.uilib.desktop.absoluteRight)):
                    self.reverse = (not self.reverse)
                else:
                    break

            (fl, ft, fw, fh,) = fromentry.GetAbsolute()
            top = ((ft - ADDTOP) - addtop)
            if ((top + self.height) > eve.triapp.uilib.desktop.absoluteBottom):
                top = ((((ft + fh) + ADDTOP) + subbottom) - self.height)
            if (self.reverse and side):
                side.width = 10
                side.left = (self.width - side.width)
        elif position:
            (x, y,) = position
        else:
            (x, y,) = (eve.triapp.uilib.x, eve.triapp.uilib.y)
        if (origin == 'topleft'):
            left = x
            top = (y - addtop)
        elif (origin == 'bottomleft'):
            left = x
            top = ((y - self.height) + subbottom)
        elif (origin == 'bottomright'):
            left = (x - self.width)
            top = ((y - self.height) + subbottom)
        elif (origin == 'topright'):
            left = (x - self.width)
            top = (y - addtop)
        else:
            raise ValueError, "origin must be one of 'topleft', 'topright', 'bottomleft', 'bottomright'"
        if (left < 0):
            left = 0
        elif ((left + self.width) > eve.triapp.uilib.desktop.absoluteRight):
            left = (eve.triapp.uilib.desktop.absoluteRight - self.width)
        if (top < 0):
            top = 0
        elif ((top + self.height) > eve.triapp.uilib.desktop.absoluteBottom):
            top = (eve.triapp.uilib.desktop.absoluteBottom - self.height)
        if edge:
            if (left < p.left):
                edge.width = 4
        self.left = left
        self.top = top
        self.state = uix.UI_NORMAL



    def OnEntryEnter(self, entry):
        entry._OnMouseEnter()
        eve.Message('ContextMenuEnter')
        if self.fromentry:
            self.DoEntryTrace(entry)
        if (entry != self.hilitedentry):
            self.hilitedentry = entry
            if self.submenu:
                self.DoSubmenuCollapse()
            if (entry.flags & ENTRY_HASSUBMENU):
                self.submenuTimer = base.AutoTimer(settings.user.ui.Get('menuExpandTime', 10), self.DoSubmenuExpand, entry)



    def OnEntryExit(self, entry):
        if not (self.submenu and (self.submenu.fromentry == entry)):
            entry._OnMouseExit()
            if self.fromentry:
                if self.submenu:
                    self.DoEntryTrace(entry)
                else:
                    self.sr.trace.top = 99999



    def DoSubmenuExpand(self, entry):
        self.submenuTimer = None
        self.DoSubmenuCollapse()
        if (entry == self.hilitedentry):
            entry._OnMouseEnter()
            if self.fromentry:
                self.DoEntryTrace(entry)
            self.submenu = Menu(blue.os.LoadObject('res:/UI/Shared/contextualmenu.blue'))
            self.submenu.Setup(entry.GetSubContent(), fromentry=entry, reverse=self.reverse, entryheight=self.entryheight)



    def DoSubmenuCollapse(self):
        if self.submenu:
            self.submenu.KillMe()
            self.submenu = None



    def DoEntryTrace(self, entry):
        (fl, ft, fw, fh,) = self.fromentry.GetAbsolute()
        (el, et, ew, eh,) = entry.GetAbsolute()
        if ((et + (eh / 2)) > (ft + (fh / 2))):
            top = ft
            if self.reverse:
                bottom = et
            else:
                bottom = (et + eh)
        else:
            bottom = (ft + fh)
            if self.reverse:
                top = (et + eh)
            else:
                top = et
        self.sr.trace.top = (top - self.absoluteTop)
        self.sr.trace.height = (bottom - top)



    def KillMe(self):
        self.submenuTimer = None
        if self.submenu:
            self.submenu.KillMe()
            self.submenu = None
        if self.fromentry:
            self.fromentry._OnMouseExit()
        if not self.destroyed:
            self.Close()




def CreateMenu(menu = None, *args, **kwargs):
    if not menu:
        return 
    else:
        obj = Menu(blue.os.LoadObject('res:/UI/Shared/contextualmenu.blue'))
        obj.Setup(menu, *args, **kwargs)
        return obj



class Scroll(uicls.Scroll):
    __guid__ = 'spiffy.Scroll'

    def GetRootEntries(self):
        root = []
        skip = 0
        sl = 3258357
        for entry in self.sr.nodes:
            sl = min(sl, entry.Get('sublevel', 0))
            if skip:
                skip -= 1
            else:
                root.append(entry)
            if (entry.GetSubContent or isinstance(entry.panel, listentry.Group)):
                if entry.subEntries:
                    skip += len(entry.subEntries)

        self.lowestsublevel = sl
        return root



    def Sort(self, by = None, reversesort = 0, forceHilite = 0):
        if self.smartSort:
            uicls.Scroll.Sort(self, by, reversesort, forceHilite)
            return 
        try:
            idx = self.sr.headers.index(by)
        except:
            idx = None

        def SubSort(entries):
            groups = []
            items = []
            skip = 0
            div = None
            for entry in entries:
                val = (self.GetSortValue(by, entry, idx), (entry.label or entry.text))
                if (entry.GetSubContent or isinstance(entry.panel, listentry.Group)):
                    groups.append((val, entry))
                elif (entry.__guid__ == 'listentry.Divider'):
                    div = entry
                else:
                    items.append((val, entry))

            groups.sort()
            items.sort()
            if reversesort:
                groups.reverse()
                items.reverse()
            neworder = []
            for g in groups:
                entry = g[1]
                neworder.append(entry)
                if entry.subEntries:
                    neworder += SubSort(entry.subEntries)

            for i in items:
                neworder.append(i[1])

            if div:
                neworder.append(div)
            return neworder


        self.sr.entries = SubSort(self.GetRootEntries())
        self.RefreshIndex('Sort')
        self.UpdatePosition(fromWhere='Sort')
        if ((self.sr.sortBy != by) or forceHilite):
            self.HiliteSorted(by, reversesort)
            self.sr.sortBy = by



    def RecursiveOpen(self, entry, recurse = True):
        if (entry.GetSubContent and uicore.registry.GetListGroupOpenState(entry.id)):
            entry.open = 1
            entry.subEntries = entry.GetSubContent(entry)
            if entry.subEntries:
                if recurse:
                    for e in entry.subEntries:
                        self.RecursiveOpen(e)

            else:
                entry.subEntries.append(listentry.Get('Generic', {'label': 'No item',
                 'sublevel': (entry.Get('sublevel', 0) + 1)}))
            return entry.subEntries
        entry.open = 0



    def ReloadEntry(self, entry):
        if entry.id:
            if entry.subEntries:
                entry.open = 0
                rm = entry.subEntries
                entry.subEntries = []
                self.RemoveEntries(rm)
            entries = self.RecursiveOpen(entry, False)
            if entries:
                self.AddEntries((entry.idx + 1), entries, entry)



    def AddEntries(self, fromIdx, entries, parentEntry = None, **kwargs):
        wnd = uix.GetWindowAbove(self)
        if (wnd and (not wnd.destroyed)):
            wnd.ShowLoad()
        if (fromIdx == -1):
            fromIdx = len(self.sr.entries)
        newentries = []
        delayed = []
        for entry in entries:
            newentries.insert(fromIdx, entry)
            if entry.subEntries:
                entry.open = 1
                self.CollectEntries(entry, newentries)
            elif entry.GetSubContent:
                delayed.append(entry)
            entry.open = 0

        if self.debug:
            log.general.Log('------------ ADDENTRIES', log.fatal)
            for entry in newentries:
                log.general.Log(('ADD: %s' % entry.label), log.fatal)

        idx = fromIdx
        for entry in newentries:
            entry.panel = None
            entry.idx = idx
            entry.selected = entry.isSelected
            if entry.PreLoadFunction:
                entry.PreLoadFunction(entry)
            idx += 1
            entry.BlockOpenWindow = True

        self.sr.entries[fromIdx:fromIdx] = newentries
        self.CheckTabStops('AddEntries')
        self.RefreshIndex('AddEntries')
        if self.GetSortBy():
            uix.TakeTime('VirtualScroll::AddEntries::UpdateSizes', self.UpdateSizes)
            uix.TakeTime('VirtualScroll::AddEntries::RefreshSort', self.RefreshSort)
        else:
            uix.TakeTime('VirtualScroll::AddEntries::UpdatePosition', self.UpdatePosition, updateSizes=1)
        for entry in delayed:
            self.ReloadEntry(entry)

        if (wnd and (not wnd.destroyed)):
            wnd.HideLoad()



    def CollectEntries(self, fromEntry, storage):
        for entry in fromEntry.subEntries:
            storage.append(entry)
            if entry.subEntries:
                self.CollectEntries(entry, storage)
                entry.open = 1
            else:
                entry.open = 0




    def RemoveEntries(self, entries):
        wnd = uix.GetWindowAbove(self)
        if (wnd and (not wnd.destroyed)):
            wnd.ShowLoad()
        killentries = []
        for entry in entries:
            killentries.append(entry)
            if entry.subEntries:
                self.CollectEntries(entry, killentries)
                entry.subEntries = []

        if self.debug:
            log.general.Log('------------ REMOVEENTRIES', log.fatal)
            for entry in killentries:
                log.general.Log(('REMOVE: %s' % entry.label), log.fatal)

        for entry in killentries:
            if entry.panel:
                self.RecyclePanel(entry.panel, 'RemoveEntries')
            self.sr.entries.remove(entry)

        self.RefreshIndex('RemoveEntries')
        self.UpdatePosition(fromWhere='RemoveEntries', updateSizes=1)
        if (wnd and (not wnd.destroyed)):
            wnd.HideLoad()



MARK_NONE = 0
MARK_LINE = 1
MARK_LEAF = 2
MARK_LASTLEAF = 3
MARK_NODE0 = 4
MARK_NODE1 = 5
MARK_LASTNODE0 = 6
MARK_LASTNODE1 = 7
SIZE = 9
TREECOLOR = (1.0,
 1.0,
 1.0,
 0.5)

def VLine(where, x, y, h):
    uicls.Line(parent=where, align=uiconst.TOPLEFT, color=TREECOLOR, left=x, top=y, width=1, height=h)



def HLine(where, x, y, w):
    uicls.Line(parent=where, align=uiconst.TOPLEFT, color=TREECOLOR, left=x, top=y, width=w, height=1)



class TreeScroll(Scroll):
    __guid__ = 'spiffy.TreeScroll'

    def init(self):
        Scroll.init(self)
        self.tgcache = {}



    def GetTG(self, this, size):
        tg = self.tgcache.get((this, size), None)
        if (tg and (not tg.destroyed)):
            return tg
        else:
            N_height = ((size - SIZE) / 2)
            S_top = (N_height + SIZE)
            S_height = (size - S_top)
            B_left = (8 - (SIZE / 2))
            middle = (size / 2)

            def TGArea(name):
                a = blue.os.CreateInstance('triui.UIWindow')
                a.name = name
                a.width = 16
                a.height = size
                a.align = uix.UI_ALRIGHT
                a.state = uix.UI_DISABLED
                return a



            def TGNode(name, islast, char):
                here = TGArea(name)
                VLine(here, 8, 0, N_height)
                HLine(here, ((8 + (SIZE / 2)) + 1), middle, (SIZE / 2))
                HLine(here, B_left, N_height, (SIZE - 1))
                VLine(here, B_left, (N_height + 1), (SIZE - 1))
                HLine(here, (B_left + 1), (S_top - 1), (SIZE - 1))
                VLine(here, ((B_left + SIZE) - 1), N_height, (SIZE - 1))
                if not islast:
                    VLine(here, 8, S_top, S_height)
                if (char == '+'):
                    VLine(here, 8, (N_height + 2), (SIZE - 4))
                HLine(here, (B_left + 2), middle, (SIZE - 4))
                return here


            if (this == MARK_LINE):
                tg = TGArea('tg:Line')
                VLine(tg, 8, 0, size)
            elif (this == MARK_LEAF):
                tg = TGArea('tg:Leaf')
                VLine(tg, 8, 0, size)
                HLine(tg, 9, middle, 8)
            elif (this == MARK_LASTLEAF):
                tg = TGArea('tg:Leaf:Last')
                VLine(tg, 8, 0, middle)
                HLine(tg, 8, middle, 8)
            elif (this == MARK_NODE0):
                tg = TGNode('tg:Node:Closed', False, '+')
            elif (this == MARK_NODE1):
                tg = TGNode('tg:Node:Opened', False, '-')
            elif (this == MARK_LASTNODE0):
                tg = TGNode('tg:Node:Last:Closed', True, '+')
            elif (this == MARK_LASTNODE1):
                tg = TGNode('tg:Node:Last:Opened', True, '-')
            else:
                tg = TGArea('tg:None')
            self.tgcache[(this, size)] = tg
            return tg



    def DecorateEntry(self, entry, markers):
        subentries = entry.subNodes
        if entry.panel:
            tg = uiutil.FindChild(entry.panel, 'treeGraphic')
            if tg:
                del tg.children[:]
            else:
                tg = uicls.Container(name='treeGraphic', parent=entry.panel, align=uiconst.TOPLEFT)
            tg.top = tg.left = 0
            tg.width = (16 * entry.Get('sublevel', 0))
            tg.height = entry.panel.height
            sr = entry.panel.sr
            idx = len(markers)
            if ((idx > 1) and isinstance(entry.panel, listentry.Group)):
                sr.expander.state = uix.UI_HIDDEN
                idx -= 1
                if subentries:
                    if (markers[idx] == MARK_LEAF):
                        tg.children.append(self.GetTG(MARK_NODE1, tg.height))
                    else:
                        tg.children.append(self.GetTG(MARK_LASTNODE1, tg.height))
                elif (markers[idx] == MARK_LEAF):
                    tg.children.append(self.GetTG(MARK_NODE0, tg.height))
                else:
                    tg.children.append(self.GetTG(MARK_LASTNODE0, tg.height))
            while (idx > 1):
                idx -= 1
                tg.children.append(self.GetTG(markers[idx], tg.height))

        if subentries:
            self.DecorateGroup(subentries, markers, entry)



    def DecorateGroup(self, entries, markers, parent = None):
        if parent:
            lastrootidx = -1
            for entry in entries:
                lastrootidx = max(lastrootidx, entry.idx)

        else:
            idx = (len(entries) - 1)
            if (idx == -1):
                return 
            while ((idx > 0) and (entries[idx].__guid__ == 'listentry.Divider')):
                idx -= 1

            lastrootidx = entries[idx].idx
        oldmark = markers[-1]
        if (oldmark == MARK_LEAF):
            markers[-1] = MARK_LINE
        else:
            markers[-1] = MARK_NONE
        markers.append(MARK_NONE)
        for entry in entries:
            markers[-1] = (MARK_LEAF, MARK_LASTLEAF)[(lastrootidx == entry.idx)]
            self.DecorateEntry(entry, markers)

        del markers[-1]
        markers[-1] = oldmark



    def CheckNodes(self, *args, **kwargs):
        Scroll.CheckNodes(self, *args, **kwargs)
        self.DecorateGroup(self.GetRootEntries(), [MARK_NONE])



exports = {'spiffy.Window': Window,
 'spiffy.Menu': Menu,
 'spiffy.MenuHeader': MenuHeader,
 'spiffy.CreateMenu': CreateMenu,
 'spiffy.Scroll': Scroll,
 'spiffy.TreeScroll': TreeScroll,
 'spiffy.ENTRY_HASSUBMENU': ENTRY_HASSUBMENU,
 'spiffy.ENTRY_ISDYNAMIC': ENTRY_ISDYNAMIC,
 'spiffy.ENTRY_VADJUST': ENTRY_VADJUST}

